#-*- coding: utf-8 -*-
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from django_model_utils.models import StatMixin, PageMixin, StatusMixin, ClonableMixin, StatClonableMixin
from tagging.fields import TagField
from tagging.models import Tag
from gironimo.category.models import Category


class Post(StatMixin, models.Model):
    user = models.ForeignKey(User, related_name='posts')
    slug = models.SlugField(max_length=200, unique=True, null=True)
    
    def _cleanup_states(self):
        try:
            del self._live_revision
        except AttributeError:
            pass
    
    def add_revision(self, revision=None, base=None):
        self._cleanup_states()
        if revision is None:
            if base is None:
                try:
                    base = self.get_live_revision()
                except PostRevision.DoesNotExist:
                    try:
                        base = self.get_latest_revision()
                    except PostRevision.DoesNotExist:
                        raise RuntimeError('Um die erste (initiale) Revision zu erstellen muss ein das Revisionsargument übergeben werden.')
            return base.clone()
        elif base is None:
            if self.slug is None and not self.has_revisions():
                from django.template.defaultfilters import slugify
                # Generate slug
                slug = slugify(revision.title)
                i = 2
                while Post.objects.filter(slug=slug):
                    slug = slugify(revision.title) + '-' + str(i)
                    i += 1
                self.slug = slug
                self.save()
            revision.entry = self
            revision.save()
            return revision
        else:
            raise RuntimeError('Entweder Revision angeben oder Base, aber nicht beides!')
    
    def has_revisions(self):
        return self.revisions.exists()
    
    def get_latest_revision(self, **kwargs):
        try:
            return self.revisions.filter(**kwargs).order_by('-created')[0]
        except AttributeError:
            raise PostRevision.DoesNotExist()
    
    def get_live_revision(self, **kwargs):
        try:
            return self._live_revision
        except AttributeError:
            self._live_revision = self.revisions.filter(**kwargs).get(status__gte.PostRevision.STATUS_LIVE)
            return self._live_revision
    
    def has_live_revision(self, **kwargs):
        try:
            self.get_live_revision()
            return True
        except PostRevision.DoesNotExist:
            return False
    
    def get_frontend_edit_revision(self):
        try:
            live_revision = self.get_live_revision()
        except PostRevision.DoesNotExist:
            live_revision = None
        draft_revisions = self.revisions.draft()
        if live_revision:
            draft_revisions = draft_revisions.filter(created__gte = live_revision.created)
        try:
            return draft_revisions.order_by('-created')[0]
        except IndexError:
            pass
        if live_revision:
            return self.add_revision(base=live_revision)
        else:
            return self.add_revision()
    
    def publish_revision(self, revision):
        self._cleanup_states()
        self.revisions.exclude(pk=revision.pk).filter(status=PostRevision.STATUS_LIVE).update(status=PostRevision.STATUS_ARCHIVE)
        self.revisions.filter(pk=revision.pk).update(status=PostRevision.STATUS_LIVE)
        revision.status = PostRevision.STATUS_LIVE
        return revision
    
    def __unicode__(self):
        return self.slug
    
    @models.permalink
    def get_absolute_url(self):
        return 'blog_detail', (), {'slug': self.slug}
    
    class Meta:
        verbose_name = _(u'Blogeintrag')
        verbose_name_plural = _(u'Blogeinträge')


class PostRevisionCloneableMixin(StatClonableMixin):
    def _clone_prepare(self, duplicate):
        super(PostRevisionCloneableMixin, self)._clone_prepare(duplicate)
        duplicate.status = self.STATUS_DRAFT


class PostRevision(StatMixin, StatusMixin, PageMixin, PostRevisionCloneableMixin, models.Model):
    post = models.ForeignKey(Post, related_name='revisions')
    category = models.ForeignKey(Category)
    
    title = models.CharField(max_length=120, verbose_name=_('Titel'))
    content = models.TextField(verbose_name=_('Inhalt'))
    pic = models.ImageField(max_length=200, upload_to='blog/logo', verbose_name=_('Artikelbild'), blank=True, null=True)
    tags = TagField()
    
    def set_tags(self, tags):
        Tag.objects.update_tags(self, tags)
    
    def get_tags(self, tags):
        return Tag.objects.get_for_object(self)
    
    def publish(self):
        self.post.publish_revision(self)
    
    def has_previous_revision(self):
        try:
            self.get_previous_revision()
            return True
        except PostRevision.DoesNotExist:
            return False
    
    def has_next_revision(self):
        try:
            self.get_next_revision()
            return True
        except PostRevision.DoesNotExist:
            return False
    
    def get_previous_revision(self):
        try:
            return PostRevision.objects.filter(post=self.post, created__lt=self.created).order_by('-created')[0]
        except IndexError:
            raise PostRevision.DoesNotExist()
    
    def get_next_revision(self):
        try:
            return PostRevision.objects.filter(post=self.post, created__gt=self.created).order_by('created')[0]
        except IndexError:
            raise PostRevision.DoesNotExist()
    
    def __unicode__(self):
        return self.title
    
    class Meta:
        verbose_name = _(u'Blogeintrag Revision')
        verbose_name_plural = _('Blogeintrag Revisionen')
